;/******************************************************************************
;/* @file   interrupt.s
;/* @brief  interrupt for ARM9
;/* @date   2025-01-11
;/* @author kerndev@foxmail.com
;/*****************************************************************************/
Stack_Size       EQU     0x00000400

	AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem_SVC    SPACE   Stack_Size
Stack_SVC
Stack_Mem_IRQ    SPACE   Stack_Size
Stack_IRQ

	AREA |.text|, CODE, READONLY
	PRESERVE8

;/*****************************************************************************/
; Mode bits and interrupt flag (I&F) defines
IRQ_MODE_NO_INT  EQU    0xD2
SVC_MODE_NO_INT  EQU    0xD3
SYS_MODE_NO_INT  EQU    0xDF

;/*****************************************************************************/
; IRQ Mode
IRQ_Handler PROC
	EXPORT IRQ_Handler
	IMPORT intc_handler
	SUB    LR, LR, #4
	LDR    SP, =Stack_IRQ
	STMFD  SP!, {R0-R3, LR}
	MRS    R0, SPSR
	STMFD  SP!, {R0}
	BL     intc_handler
	LDR    R0, =sched_tcb_now
	LDR    R1, =sched_tcb_next
	LDR    R2, [R0]
	LDR    R3, [R1]
	CMP    R2, R3
	BEQ    IRQ_RETURN
	STR    R3, [R0]
	
	MOV    R0, SP
	MSR    CPSR_c, #SYS_MODE_NO_INT
	STMFD  SP!, {R4-R12, LR}
	LDMFD  R0!, {R4}
	STMFD  SP!, {R4}
	LDMFD  R0!, {R4-R7, LR}
	STMFD  SP!, {R4-R7, LR}
	
	CMP    R2, #0
	STRNE  SP, [R2]
	LDR    SP, [R3]
	
	LDMFD  SP!, {R4-R7, LR}
	STMFD  R0!, {R4-R7, LR}
	LDMFD  SP!, {R4}
	STMFD  R0!, {R4}
	LDMFD  SP!, {R4-R12, LR}
	MSR    CPSR_c, #IRQ_MODE_NO_INT
	
IRQ_RETURN
	LDMFD  SP!, {R0}
	MSR    SPSR_cxsf, R0
	LDMFD  SP!, {R0-R3, PC}^
	ENDP

;/*****************************************************************************/
; SVC Mode
SWI_Handler PROC
	EXPORT SWI_Handler
	IMPORT sched_tcb_now
	IMPORT sched_tcb_next
	LDR    SP, =Stack_SVC
	STMFD  SP!, {R0-R3, LR}
	MRS    R0, SPSR
	STMFD  SP!, {R0}

	LDR    R0, =sched_tcb_now
	LDR    R1, =sched_tcb_next
	LDR    R2, [R0]
	LDR    R3, [R1]
	CMP    R2, R3
	BEQ    SWI_RETURN
	STR    R3, [R0]
	
	MOV    R0, SP
	MSR    CPSR_c, #SYS_MODE_NO_INT
	STMFD  SP!, {R4-R12, LR}
	LDMFD  R0!, {R4}
	STMFD  SP!, {R4}
	LDMFD  R0!, {R4-R7, LR}
	STMFD  SP!, {R4-R7, LR}
	
	CMP    R2, #0
	STRNE  SP, [R2]
	LDR    SP, [R3]
	
	LDMFD  SP!, {R4-R7, LR}
	STMFD  R0!, {R4-R7, LR}
	LDMFD  SP!, {R4}
	STMFD  R0!, {R4}
	LDMFD  SP!, {R4-R12, LR}
	MSR    CPSR_c, #SVC_MODE_NO_INT
	
SWI_RETURN
	LDMFD  SP!, {R0}
	MSR    SPSR_cxsf, R0
	LDMFD  SP!, {R0-R3, PC}^
	ENDP
	
	END
